﻿/*
 * ringpos_in.hpp
 *
 *  Created on: 2017年2月3日
 *      Author: Dylan.Gao
 */

#ifndef _DM_RINGPOS_IN_HPP_
#define _DM_RINGPOS_IN_HPP_


namespace dm{
namespace ringpos{

template<typename TRingPos1,typename TRingPos2>
inline bool isEquare( const TRingPos1& p1,const TRingPos2& p2 ){
	return p1.getPos()==p2.getPos() && p1.getCycle()==p2.getCycle();
}

template<typename TRingPos1,typename TRingPos2>
inline bool isNotEquare( const TRingPos1& p1,const TRingPos2& p2 ){
	return p1.getPos()!=p2.getPos() || p1.getCycle()!=p2.getCycle();
}

template<typename Tp,typename Tc,typename Tpp,typename Tcc>
void moveRight( Tpp& pp,Tcc& pc,const Tp& ps,Tp mn,const Tc& mc ){
	if( ps>0 ){
		if( mc>0 )
			pc += mc;
		while( mn>ps ){
			++pc;
			mn -= ps;
		}

		pp += mn;
		if( pp>=ps ){
			++pc;
			pp -= ps;
		}
	}
}

template<typename Tp,typename Tc,typename Tpp,typename Tcc>
void moveLeft( Tpp& pp,Tcc& pc,const Tp& ps,Tp mn,const Tc& mc ){
	if( ps>0 ){
		if( mc>0 )
			pc -= mc;
		while( mn>=ps ){
			--pc;
			mn -= ps;
		}

		if( mn>pp ){
			--pc;
			pp += (ps - mn);
		}else{
			pp -= mn;
		}
	}
}

template<typename TRingPos>
bool isNoMoreThanACycle( const TRingPos& p1,const TRingPos& p2 ){
	if( p1.getCycle()==p2.getCycle() ){
		if( p1.getPos()>=p2.getPos() )
			return true;
	}else if( p1.getCycle()==(p2.getCycle()+1) ){
		if( p1.getPos()<p2.getPos() )
			return true;
	}

	return false;
}

template<typename TRingPos>
inline bool isNoLessThanACycle( const TRingPos& p1,const TRingPos& p2 ){
	return isNoMoreThanACycle(p2,p1);
}

template<typename TRingPos,typename Tp>
Tp distance( const TRingPos& p1,const TRingPos& p2 ){
	if( isNoMoreThanACycle(p1,p2) ){
		if( p1.getCycle()==p2.getCycle() )
			return p1.getPos() - p2.getPos();
		else
			return p1.getSize() - p2.getPos() + p1.getPos();
	}else
		return p1.getSize();
}

}
}


#endif /* INCLUDE_DM_RINGPOS_IN_HPP_ */
